/**
 ** 译码的顶级模块
 ** 模块的输出不能连接到reg，只能用wire，否则会报下面的错
 ** cannot be driven by primitives or continuous assignment.
**/

module ID (
    input wire clk,
    input wire rst,
    input wire [31:0] pc_in,        //当前输入的PC
    input wire [31:0] now_inst,     //当前要执行的指令
    input wire wb_reg_wr_ctrl, //来自于写回阶段的寄存器写入控制信号
    input wire [31:0] wb_reg_wr_data, //来自于写回阶段的寄存器写入的内容
    input wire [4:0] wb_reg_wr_no,   //来自写回阶段的寄存器的编号
    input wire [31:0] pre_exe_result, //之前指令的运算结果，用于旁路技术
    input wire [31:0] pre_exe_inst,
    input wire [31:0] pre_mem_result,
    input wire [31:0] pre_mem_inst,
    output wire rf_wr_en,           //寄存器写信号
    output wire [1:0] rf_wr_sel,    //寄存器选择信号
    output wire [3:0] alu_ctrl,     //运算器的控制信号
    output wire [2:0] dm_rd_ctrl,   //数据存储器的读取控制信号
    output wire [1:0] dm_wr_ctrl,   //数据存储器的写入控制信号
    output wire [31:0] imm_out,     //填充过后的立即数
    output reg [31:0] src_a,
    output reg [31:0] src_b,
    output reg [31:0] reg_r2,
    output reg rs_en_out,
    output reg rt_en_out
);
    wire [2:0] imm_ctrl;     //立即数拓展控制信号
    wire [4:0] reg_a1;
    wire [4:0] reg_a2;
    wire [4:0] reg_a3;
    wire [31:0] reg_rs;
    wire [31:0] reg_rt;
    wire [31:0] reg_rs_final;
    wire [31:0] reg_rt_final;
    wire alu_a_sel;
    wire alu_b_sel;

    assign reg_a1 = now_inst[19:15];
    assign reg_a2 = now_inst[24:20];
    assign reg_a3 = now_inst[11:7];

    wire rs_en;
    wire rt_en;

    always @(*) begin
        if (alu_a_sel==0) begin
            src_a = pc_in;
        end

        if(alu_a_sel==1) begin
            if (rs_en==1) begin
                src_a = reg_rs_final;
            end
            else begin
                src_a = reg_rs;
            end
        end

        if (alu_b_sel==0) begin
            if (rt_en==1) begin
                src_b = reg_rt_final;
            end
            else begin
                src_b = reg_rt;
            end
        end

        if(alu_b_sel==1) begin
            src_b = imm_out;
        end

        //保留一个输出，后面有用
        reg_r2 = reg_rt_final;
    end

    always @(*) begin
        rs_en_out = rs_en;
        rt_en_out = rt_en;
    end

    //实例化一个控制器
    commonControl ctrl1(.now_inst(now_inst), .pc(pc_in), .rf_wr_en(rf_wr_en), .rf_wr_sel(rf_wr_sel), .alu_a_sel(alu_a_sel), .alu_b_sel(alu_b_sel), .alu_ctrl(alu_ctrl), .dm_rd_ctrl(dm_rd_ctrl), .dm_wr_ctrl(dm_wr_ctrl), .imm_ctrl(imm_ctrl));  

    //实例化立即数拓展器
    immPadding imm1(.imm_ctrl(imm_ctrl), .now_inst(now_inst), .imm_out(imm_out));  

    //实例化寄存器堆
    registers reg1(.clk(clk), .rst(rst), .now_a1(reg_a1), .now_a2(reg_a2), .now_a3(wb_reg_wr_no), .write_in(wb_reg_wr_data), .write_en(wb_reg_wr_ctrl), .now_rs(reg_rs), .now_rt(reg_rt));

    //实例化旁路前递器
    byPass by2(.alu_a_in(reg_rs), .alu_b_in(reg_rt), .pre_exe_result(pre_exe_result), .pre_mem_result(pre_mem_result), .inst(now_inst), .ex_inst(pre_exe_inst), .mem_inst(pre_mem_inst), .alu_a_out(reg_rs_final), .alu_b_out(reg_rt_final), .rs_en(rs_en), .rt_en(rt_en));
endmodule